package com.sec.etech.bpm.cust.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sec.etech.bpm.constant.DBConstant;
import com.sec.etech.bpm.cust.controller.EtechTaskController;
import com.sec.etech.bpm.cust.mapper.EtechTaskOpinionExtMapper;
import com.sec.etech.bpm.cust.model.EtechTaskOpinionExt;
import com.sec.etech.common.BpmFormActionMap;
import com.sec.etech.common.LifeCycle;
import com.sec.etech.common.SpringUtil;
import com.sec.etech.file.service.EtechWebUploaderService;
import com.sec.etech.form.cust.util.FormDefDataUtil;
import com.sec.etech.org.service.EtechUserUtil;
import com.sec.etech.sys.msg.EtechMailService;
import com.sec.etech.sys.msg.model.EtechEmailMessage;
import com.sec.etech.sys.util.RequestHolder;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.apache.commons.collections4.CollectionUtils;
import org.openbpm.base.api.exception.BusinessException;
import org.openbpm.base.api.exception.BusinessMessage;
import org.openbpm.base.api.response.impl.ResultMsg;
import org.openbpm.base.core.id.IdUtil;
import org.openbpm.base.core.util.AppUtil;
import org.openbpm.base.core.util.ExceptionUtil;
import org.openbpm.base.core.util.StringUtil;
import org.openbpm.bpm.api.constant.ActionType;
import org.openbpm.bpm.api.engine.action.cmd.FlowRequestParam;
import org.openbpm.bpm.api.engine.action.cmd.TaskActionCmd;
import org.openbpm.bpm.api.engine.data.BpmFlowDataAccessor;
import org.openbpm.bpm.api.engine.data.result.BpmFlowData;
import org.openbpm.bpm.api.engine.data.result.BpmFlowTaskData;
import org.openbpm.bpm.api.engine.data.result.FlowData;
import org.openbpm.bpm.api.exception.BpmStatusCode;
import org.openbpm.bpm.api.model.task.IBpmTask;
import org.openbpm.bpm.core.manager.BpmTaskManager;
import org.openbpm.bpm.core.model.BpmTask;
import org.openbpm.bpm.engine.action.cmd.DefaultInstanceActionCmd;
import org.openbpm.bpm.engine.action.cmd.DefualtTaskActionCmd;
import org.openbpm.bpm.rest.controller.BpmTaskController;
import org.openbpm.bus.api.model.IBusinessData;
import org.openbpm.form.api.model.FormType;
import org.openbpm.form.model.FormDefData;
import org.openbpm.form.service.FormDefDataService;
import org.openbpm.org.api.model.IUser;
import org.openbpm.sys.api.service.ISysDataSourceService;
import org.openbpm.sys.util.ContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EtechBpmService {
    @Autowired
    ISysDataSourceService sysDataSourceService;
    @Resource
    private FormDefDataService formDefDataService;
    @Resource
    private BpmTaskManager bpmTaskManager;
    @Autowired
    BpmFormActionMap actionMap;

    // 避免循环依赖
//    @Autowired
//    EtechBpmHelper etechBpmHelper;

    @Resource
    EtechMailService etechMailService;
    @Resource
    EtechTaskOpinionExtMapper taskOpinionExtMapper;
    @Resource
    BpmTaskController bpmTaskController;
    @Resource
    BpmFlowDataAccessor bpmFlowDataAccessor;
    @Resource
    JdbcTemplate jdbcTemplate;
    @Resource
    EtechWebUploaderService etechWebUploaderService;
    @Resource
    EtechTaskController etechTaskController;

    // 流程线程池，用于批量提交，自动提交节点, 迁移到EtechBpmHelper
    // private final ExecutorService executorService = new ThreadPoolExecutor(50, 200, 1, TimeUnit.SECONDS, new LinkedBlockingDeque());

    /**
     * 节点批量处理
     *
     * @param flowParams
     * @return
     */
    public JSONArray doActions(List<JSONObject> flowParams) {
        EtechBpmHelper etechBpmHelper = AppUtil.getBean(EtechBpmHelper.class);
        return etechBpmHelper.doActions(flowParams);
        //迁移到EtechBpmHelper
//        JSONArray results = new JSONArray();
//        IUser curUser = ContextUtil.getCurrentUser();
//        List<Future<JSONObject>> futures = new ArrayList<>();
//        //ExecutorService executorService = ThreadUtil.newExecutor(flowParams.size());
//        flowParams.forEach((jsonObject) -> {
//            Future<JSONObject> future = executorService.submit(new Callable<JSONObject>() {
//                public JSONObject call() throws Exception {
//                    JSONObject var4;
//                    try {
//                        ContextUtil.setCurrentUser(curUser);
//                        var4 = doAction(jsonObject);
//                    } catch (Exception e) {
//                        JSONObject result = new JSONObject();
//                        result.put("bizId", jsonObject.getString("bizId"));
//                        result.put("flag", "0");
//                        result.put("msg", ExceptionUtil.getRootErrorMseeage(e));
//                        var4 = result;
//                    } finally {
//                        ContextUtil.clearAll();
//                    }
//                    return var4;
//                }
//            });
//            futures.add(future);
//        });
//        futures.forEach((future) -> {
//            try {
//                results.add(future.get());
//            } catch (Exception var4) {
//                JSONObject result = new JSONObject();
//                result.put("flag", "0");
//                result.put("msg", ExceptionUtil.getRootErrorMseeage(var4));
//                results.add(result);
//            }
//
//        });
//        // executorService.shutdown();  //改为共用
//        return results;
    }

    /**
     * 单个节点提交
     *
     * @param flowParams
     * @return
     */
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public JSONObject doAction(JSONObject flowParams) {
        IUser currentUser = ContextUtil.getCurrentUser();//暂存

        JSONObject result = new JSONObject();
        try {
            IUser actionUser = null;
            // 兼容现有代码
            if(flowParams.get("handler") != null){
                actionUser = (IUser) flowParams.get("handler");
            }
            if(flowParams.get("actionUserId") != null){
                actionUser = EtechUserUtil.getUserById(flowParams.getString("actionUserId"));
            }
            if(actionUser==null){
                if(currentUser!=null){
                    actionUser = currentUser;
                }else{
                    actionUser = EtechUserUtil.getUserAdmin();
                }
            }

            ContextUtil.setCurrentUser(actionUser);
            FlowRequestParam flowParam = JSONObject.toJavaObject(flowParams, FlowRequestParam.class);
            String formKey = flowParams.getString("formKey");
            String bizId = flowParams.getString("bizId");
            //参数检查
            String flagAutosubmitTask = flowParams.getString("flagAutosubmitTask");
            String errorMsg = null;
            if (StringUtil.isEmpty(flowParam.getDefId()) && StringUtil.isEmpty(flowParam.getDefKey())) {
                errorMsg = "defId和defKey不能同时为空！";
            } else if ((flowParam.getData() == null || flowParam.getData().isEmpty())
                    && (StringUtil.isEmpty(bizId) || StringUtil.isEmpty(formKey))) {
                if(!"1".equals(flagAutosubmitTask)){
                    errorMsg = "data和bizId、formKey不能同时为空！";
                }
            } else if (flowParam.getTaskId() == null || flowParam.getInstanceId() == null) {
                errorMsg = "taskId、instanceId不能为空！";
            } else if (flowParam.getExtendConf() == null || StringUtil.isEmpty(flowParam.getExtendConf().getString("nodeId"))) {
                errorMsg = "扩展配置nodeId不能为空！";
            } else if (StringUtil.isEmpty(flowParam.getAction())) {
                errorMsg = "action不能为空！";
            }
            if (StringUtil.isNotEmpty(errorMsg)) {
                result.put("bizId", bizId);
                result.put("flag", "0");
                result.put("msg", errorMsg);
                return result;
            }

            if (StringUtil.isEmpty(flowParam.getDefId()) && StringUtil.isNotEmpty(flowParam.getDefKey())) {
                JdbcTemplate jdbcTemplate = sysDataSourceService.getJdbcTemplateByKey(DBConstant.BPM_DB);
                String sql = "select id_ from bpm_definition where key_='{}' and is_main_ ='Y'";
                String defId = null;
                try {
                    defId = jdbcTemplate.queryForObject(StrUtil.format(sql, flowParam.getDefKey()), String.class);
                } catch (Exception e) {
                }
                if (defId == null) {
                    throw new BusinessMessage("流程定义查找失败！ flowKey： " + flowParam.getDefKey(), BpmStatusCode.DEF_LOST);
                }
                flowParam.setDefId(defId);
            }
            if (flowParam.getData() == null || flowParam.getData().size() == 0) {
                FormDefData formDefData = formDefDataService.getByFormDefKey(formKey, bizId);
                if (formDefData == null || formDefData.getData() == null) {
                    throw new BusinessMessage("流程表单数据查找失败！ formKey： " + formKey, BpmStatusCode.FLOW_BUS_DATA_LOSE);
                }
                // 拿到业务数据并设置
                flowParam.setData(formDefData.getData());
            }
            Map<String, String> map = this.doAction(flowParam);
            result.put("bizId", bizId);
            result.put("flag", "1");
            result.put("msg", map.get("resultMsg") + "成功");
            result.put("instanceId", map.get("instanceId"));
            result.put("nodeId", map.get("nodeId"));
        } catch (Exception e) {
            e.printStackTrace();
            result = new JSONObject();
            result.put("bizId", flowParams.getString("bizId"));
            result.put("flag", "0");
            result.put("msg", ExceptionUtil.getRootErrorMseeage(e));
        } finally {
            if(currentUser!=null){
                ContextUtil.setCurrentUser(currentUser);
            }
        }
        return result;
    }



    /**
     * 任务指派
     *
     * @param taskId
     * @param userId
     * @param userName
     * @return
     * @throws Exception
     */
    public String assignTask(String taskId, String userId, String userName) throws Exception {
        this.bpmTaskManager.assigneeTask(taskId, userId, userName);
        return "success";
    }

    /**
     * 自动提交当前节点（使用schedule）
     * @param taskActionModel
     */
    public void saveAutoSubmitTask(TaskActionCmd taskActionModel){
        saveAutoSubmitTask(taskActionModel, null);
    }
    public void saveAutoSubmitTask(TaskActionCmd taskActionModel, String remark){
        EtechBpmHelper etechBpmHelper = AppUtil.getBean(EtechBpmHelper.class);
        etechBpmHelper.saveAutoSubmitTask(taskActionModel, remark);
    }

    public void saveAutoSubmitTask(String taskId, String action, String userId, String bizId, Date submitTime, String remark){
        EtechBpmHelper etechBpmHelper = AppUtil.getBean(EtechBpmHelper.class);
        etechBpmHelper.saveAutoSubmitTask(taskId,action, userId, bizId, submitTime, remark);
    }

    /**
     * 自动提交当前节点（使用threadLocal）
     *
     * @param taskActionModel
     */
    @Transactional
    public void autoSubmitNode(TaskActionCmd taskActionModel) {
        // 提交当前节点完成
        try {
            JSONObject taskData = createTaskDate(taskActionModel);
            EtechBpmHelper etechBpmHelper = AppUtil.getBean(EtechBpmHelper.class);
            etechBpmHelper.setAutoSubmitTaskInThread(taskData.getString("taskId"));
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("自动提交任务失败", e);
        }
    }

    private JSONObject createTaskDate(TaskActionCmd taskActionModel) {
        JSONObject taskData = new JSONObject();

        BpmTask task = (BpmTask) taskActionModel.getBpmTask();
        taskData.put("taskId", task.getTaskId());
        taskData.put("assigneeId", task.getAssigneeId());
        JSONObject dataObject = new JSONObject();
        Map<String, IBusinessData> bizDataMap = taskActionModel.getBizDataMap();
        if (bizDataMap != null && bizDataMap.size() > 0) {
            String key = bizDataMap.keySet().iterator().next();
            taskData.put("bizKey", key);
            IBusinessData businessData = bizDataMap.get(key);
            if (businessData != null) {
                taskData.put("bizId", businessData.getPk());
                dataObject.put(key, businessData.getData());
            }
        }
        taskData.put("busData", dataObject);
        return taskData;
    }

    /**
     * 发起新流程
     *
     * @param defKey      流程key
     * @param formKey     表单key
     * @param bizId       业务表ID
     * @param callBackObj 回调函数信息
     */
    public void startNewBpmInst(String defKey, String formKey, String bizId, JSONObject callBackObj) {
        try {
            JSONObject jsonObject = new JSONObject();
            String defId = null;
            String sql = "select id_ from bpm_definition where key_='{}' and is_main_ ='Y'";
            try {
                JdbcTemplate jdbcTemplate = sysDataSourceService.getJdbcTemplateByKey(DBConstant.PLAN_DB);
                defId = jdbcTemplate.queryForObject(StrUtil.format(sql, defKey), String.class);
            } catch (Exception e) {
                defId = null;
            }
            if (defId == null) {
                log.error("流程定义查找失败！ flowKey： {}", defKey);
                return;
            }
            jsonObject.put("bizId", bizId);
            jsonObject.put("defId", defId);
            FormDefData formDefData = formDefDataService.getByFormDefKey(formKey, bizId);
            if (formDefData == null || formDefData.getData() == null) {
                log.error("流程表单数据查找失败！ flowformkey：{} ", formKey);
                return;
            }
            jsonObject.put("data", formDefData.getData());
            jsonObject.put("action", ActionType.START.getKey());
            jsonObject.put("opinion", ActionType.START.getName());
            jsonObject.put("callBack", callBackObj);
            EtechBpmHelper etechBpmHelper = AppUtil.getBean(EtechBpmHelper.class);
            etechBpmHelper.setStartNewBpmInstInThread(jsonObject);
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("自动提交任务失败", e);
        }
    }

    /**
     * 发起新流程
     *
     * @param templateId
     * @param bizId
     * @param callBackObj
     */
    public void startNewBpmInst(String templateId, String bizId, JSONObject callBackObj) {
        JdbcTemplate jdbcTemplate = sysDataSourceService.getJdbcTemplateByKey(DBConstant.PLAN_DB);
        String tempSql = "select flowDefKey,flowformkey from proj_plantask_template where enable=1 and id=" + templateId;
        List<Map<String, Object>> templateList = jdbcTemplate.queryForList(tempSql);
        if (templateList == null || templateList.size() < 1 || StringUtil.isEmpty(templateList.get(0).get("flowDefKey").toString())
                || StringUtil.isEmpty(templateList.get(0).get("flowformkey").toString())) {
            log.error("流程模板未配置，请检查：templateId={}", templateId);
            return;//"该流程模板未配置，请检查";
        }
        this.startNewBpmInst(templateList.get(0).get("flowDefKey").toString(), templateList.get(0).get("flowformkey").toString(), bizId, callBackObj);
    }

    /**
     * 任务提交公共方法
     *
     * @param flowParam
     * @return
     * @throws Exception
     */
    public Map<String, String> doAction(FlowRequestParam flowParam) throws Exception {
        Map<String, String> map = new HashMap<>();
        BpmTask task = bpmTaskManager.get(flowParam.getTaskId());
        //String instanceid = flowParam.getInstanceId();
        //log.info("flowParam {} of {}", BeanUtil.beanToMap(flowParam), task.getNodeId());

        // 文件拦截处理 -- 移到外部方法中
        if(!precheck4doAction(map, flowParam, task)){
            return map;
        }

        DefualtTaskActionCmd taskModel = new DefualtTaskActionCmd(flowParam);
        String actionName = "";
        try {
            actionName = taskModel.executeCmd();
        } catch (ActivitiObjectNotFoundException ex) {
            // 用于修改单多节点会签，如果提交报错的话，会用会签同意来提交！
            flowParam.setAction("signAgree");
            taskModel = new DefualtTaskActionCmd(flowParam);
            actionName = taskModel.executeCmd();
        }

        map.put("resultMsg", actionName);
        map.put("instanceId", taskModel.getInstanceId());
        if (taskModel.getBpmTask() != null) {
            map.put("nodeId", taskModel.getNodeId());
        }
        // 执行完成后操作
        if (flowParam.getAction().equals("oppose")) {
            // TODO
            if (task != null) {
                BpmFormActionMap.OpposeAction action = actionMap.getOpposeAction(task.getNodeId());
                JSONObject data = flowParam.getData();
                if (action != null) {
                    if (data.containsKey(action.getBusinessKey())) {
                        String id = data.getJSONObject(action.getBusinessKey()).getString(action.getBusinessId());
                        action.getAction().accept(id);
                    }
                }
            }
        }

        // 单节点自动提交（简易版）
        autoSubmitNodeSimple(flowParam, taskModel);


        // 自动完成节点？
        callbackAutoSubmitTask(map, flowParam);

        //新启动另外流程
        callbackNewBpmInst(map, taskModel);

        if ("carbonCopy".equals(taskModel.getActionName())) {
            sendCcMail(taskModel);
        }
        return map;
    }

    /**
     * 回调自动完成任务
     * @param result
     * @param flowParam
     */
    private void callbackAutoSubmitTask(Map<String, String> result, FlowRequestParam flowParam){
        EtechBpmHelper etechBpmHelper = AppUtil.getBean(EtechBpmHelper.class);
        Map<String, String> taskIds = etechBpmHelper.getAutoSubmitTask();
        if (taskIds == null || taskIds.size() == 0) {
            return;
        }
        // 是否异步调用？
        //boolean isAsyn = false;
        // TODO 需要改成由发起程序来确认
        List<Future<JSONObject>> futures = new ArrayList<>();
        for (String taskId : taskIds.values()) {
            try {
                //Future<JSONObject> future = executorService.submit(new Callable(){
                    //@Override
                    //public Object call() throws Exception {
                        JSONObject jsonResult = new JSONObject();
                        //try{
                            IUser currentUser = ContextUtil.getCurrentUser();
                            //需要更改为改节点的处理人
                            ContextUtil.setCurrentUser(EtechUserUtil.getUserAdmin());
                            try {
                                //自动完成的节点这里重新查询表单数据，防止这里使用的表单数据还是上一个节点的数据，导致修改的数据被这里重新覆盖了
                                BpmFlowData bpmFlowData = bpmFlowDataAccessor.getFlowTaskData(taskId, FormType.PC);
                                flowParam.setData(bpmFlowData.getData());
                            } catch (Exception e) {
                                log.warn("自动节点重新获取表单数据异常", e);
                            }
                            flowParam.setTaskId(taskId);
                            flowParam.setAction(ActionType.AGREE.getKey());
                            DefualtTaskActionCmd taskModel = new DefualtTaskActionCmd(flowParam);
                            String actionName = taskModel.executeCmd();
                            ContextUtil.setCurrentUser(currentUser);

                            jsonResult.put("resultMsg", actionName);
                            jsonResult.put("instanceId", taskModel.getInstanceId());
                            jsonResult.put("nodeId", taskModel.getNodeId());

                        /*}catch(Exception e){
                            String errorMsg = "callbackAutoSubmitTask taskId="+taskId+":"+e.getMessage();
                            jsonResult.put("errorMsg", errorMsg);
                            log.warn(errorMsg, e);
                        }*/
                        //return jsonResult;
                    //}
                //});
                //futures.add(future);
            } catch (Exception e) {
                e.printStackTrace();
                //throw new Exception(e);
            } finally {
                etechBpmHelper.removeAutoSubmitTaskInThread(taskId);
            }
        }
        // 检查返回结果？
        /*if(!isAsyn){
            // 非异步才检查结果
            JSONArray results = new JSONArray();
            futures.forEach((future) -> {
                try {
                    results.add(future.get());
                } catch (Exception e4) {
                    JSONObject result1 = new JSONObject();
                    result1.put("flag", "0");
                    result1.put("msg", ExceptionUtil.getRootErrorMseeage(e4));
                    results.add(result1);
                }
            });
        }*/
    }

    /**
     * 回调新启动另外流程 - 从doAction中迁移出来
     */
    private void callbackNewBpmInst(Map<String, String> result, DefualtTaskActionCmd taskModel){
        EtechBpmHelper etechBpmHelper = AppUtil.getBean(EtechBpmHelper.class);
        Map<String, JSONObject> startData = etechBpmHelper.getStartNewBpmInst();
        String exceptionMsg = null;
        List<Exception> exceptionList = new ArrayList();
        if (startData != null && startData.size() > 0) {
            for (Map.Entry<String, JSONObject> entry : startData.entrySet()) {
                try {
                    JSONObject startObject = entry.getValue();
                    FlowRequestParam newFlowParam = JSONObject.toJavaObject(startObject, FlowRequestParam.class);
                    DefaultInstanceActionCmd instanceCmd = new DefaultInstanceActionCmd(newFlowParam);

                    // 执行command
                    String actionName = instanceCmd.executeCmd();

                    if(result!=null){
                        result.put("resultMsg", actionName);
                        if(taskModel!=null){
                            result.put("instanceId", taskModel.getInstanceId());
                            result.put("nodeId", taskModel.getNodeId());
                        }
                    }

                    String instanceId = instanceCmd.getInstanceId();
                    //调用回掉方法
                    JSONObject callBackParam = startObject.getJSONObject("callBack");
                    if (callBackParam != null) {//方法回调，增加参数
                        JSONObject params = callBackParam.getJSONObject("params");
                        if (params != null) {
                            callBackParam.getJSONObject("params").put("instanceId", instanceId);
                        } else {
                            params = new JSONObject();
                            params.put("instanceId", instanceId);
                            callBackParam.put("params", params);
                        }
                        etechBpmHelper.callBack(callBackParam);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    exceptionList.add(e);
                    String errorMsg = "callbackNewBpmInst key="+entry.getKey()+":"+e.getMessage();
                    log.warn(errorMsg, e);
                    if(exceptionMsg==null){
                        exceptionMsg = errorMsg;
                    }else{
                        exceptionMsg = exceptionMsg+"\r\n"+errorMsg;
                    }
                    // throw new Exception(e);
                } finally {
                    etechBpmHelper.removeStartNewBpmInstInThread(entry.getKey());
                }
            }
        }
        // TODO how to deal exceptions?
        if(CollectionUtils.isNotEmpty(exceptionList)){
            throw new BusinessException(exceptionMsg, exceptionList.get(exceptionList.size()-1));
        }
    }

    private boolean precheck4doAction(Map<String, String> result, FlowRequestParam flowParam, BpmTask task) throws Exception {
        if (flowParam.getAction().equals("agree") || flowParam.getAction().equals("submit") || flowParam.getAction().equals("autoagree")) {
            // TODO 拦截保存，尝试干点什么, 可能会炸
            if (task != null) {
                List<String> action = actionMap.getAgreeAction(task.getNodeId());
                //表单文件信息
                JSONObject fileData = new JSONObject();
                //JSONObject cloneData = null;
                if (action != null) {
                    log.info("get action:" + action);
                    String businessKey = action.get(0);

                    String[] bkeys = businessKey.split(";");

                    String beanKey = action.get(1);

                    String[] kkeys = beanKey.split(";");

                    JSONObject data = flowParam.getData();

                    //cloneData = (JSONObject) data.clone();
                    data.put("nodeId", task.getNodeId());
                    String instanceid = flowParam.getInstanceId();
                    data.put("instanceId", instanceid);
                    data.put("taskId", task.getTaskId());
                    data.put("defKey", flowParam.getDefKey());
                    //log.info("get data:" + data);

                    for (int i = 0; i < bkeys.length; i++){
                        String key = bkeys[i];
                        String bkey = kkeys[i];
                        if (data.containsKey(key)) {
                            LifeCycle lifeCycle = SpringUtil.getBean(kkeys[0], LifeCycle.class);
                            if (lifeCycle != null) {
                                if (lifeCycle.checkPermission(null, null, data)) {
                                    lifeCycle.beforeSave(null, null, data);
                                    if (data != null) {
                                        if (data.getJSONArray("add_file_list") != null) {
                                            fileData.put("add_file_list", data.getJSONArray("add_file_list"));
                                            data.remove("add_file_list");
                                        }
                                        if (data.getJSONArray("del_file_list") != null) {
                                            fileData.put("del_file_list", data.getJSONArray("del_file_list"));
                                            data.remove("del_file_list");
                                        }

                                        // 检查公用更新字段
                                        data.remove("nodeId");
                                        data.remove("instanceId");
                                        data.remove("taskId");
                                        data.remove("defKey");
                                        for (String key1 : data.keySet()) {
                                            JSONObject itemJson = data.getJSONObject(key1);
                                            FormDefDataUtil.checkCommonUpdateDate(itemJson);
                                            data.put(key1, itemJson);
                                        }
                                    }
                                    //data.remove("nodeId");
                                    //System.out.println(data);
                                    JSONObject result1 = this.formDefDataService.saveFormDefData(data, bkey, false);
                                    // 日志内容太多，如调试需要输出建议限制最大输出大小
                                    //log.info("get result:" + result1);
                                    data.put("nodeId", task.getNodeId());
                                    data.put("instanceId", instanceid);
                                    data.put("taskId", task.getTaskId());
                                    data.put("defKey", flowParam.getDefKey());
                                    lifeCycle.afterSave(null, null, data);
                                } else {
                                    throw new Exception(lifeCycle.permissionDenied());
                                }

                                String needSubmit = action.get(2);
                                if (needSubmit.equals("F")) {
                                    log.info("完成我的拦截方法");
                                    result.put("resultMsg", "保存");
                                    //return result;
                                    return false;
                                }
                            }
                        }
                    }
                } else {
                    JSONObject data = flowParam.getData();
                    if (data != null) {
                        if (data.getJSONArray("add_file_list") != null) {
                            fileData.put("add_file_list", data.getJSONArray("add_file_list"));
                            data.remove("add_file_list");
                        }
                        if (data.getJSONArray("del_file_list") != null) {
                            fileData.put("del_file_list", data.getJSONArray("del_file_list"));
                            data.remove("del_file_list");
                        }
                    }
                }
                // 保存表单后操作文件
                etechWebUploaderService.handlerFileAfterSaveForm(fileData);
            }
        }
        return true;
    }


    private void autoSubmitNodeSimple3(String taskid, String instanceid) throws Exception {
        ResultMsg<FlowData> flowDataResultMsg = etechTaskController.getTaskDataReal(taskid, "pc");

        System.out.println(flowDataResultMsg);

        FlowData flowData = flowDataResultMsg.getData();


        FlowRequestParam flowParam = new FlowRequestParam();
        flowParam.setData(flowData.getData());
        flowParam.setAction("agree");
        flowParam.setInstanceId(instanceid);
        flowParam.setTaskId(taskid);
        JSONObject obj = new JSONObject();
        obj.put("nodeId", "");

        flowParam.setExtendConf(obj);
        flowParam.setOpinion("提交");

        doAction(flowParam);



    }

    public void autoSubmitNodeSimple2(String nodeKey, String nodeAction, String instanceid) {
        log.info("自动跳过 {} {} {}", nodeKey, nodeAction, instanceid);
        if (isNextNodeAuto2(nodeAction, nodeKey)) {
            FlowRequestParam autoExecuteFlowParam = new FlowRequestParam();
            String autoExecuteInstanceId = instanceid;
            if (StrUtil.isNullOrUndefined(autoExecuteInstanceId)) {
                log.info("autoExecuteInstanceId 为 null 或空 ");
            } else {
                JdbcTemplate jdbcTemplate = sysDataSourceService.getJdbcTemplateByKey(DBConstant.PLAN_DB);
                List<Map<String, Object>> autoExecuteList = jdbcTemplate.queryForList("SELECT id_ FROM bpm_task WHERE inst_id_=?", autoExecuteInstanceId);
                if (autoExecuteList.size() == 1) {
                    if (autoExecuteList.get(0).get("id_") == null) {
                        log.info("get bpm_task id_ == null");
                    } else {
                        log.info("get bpm_task id_ != null 系统自动通过");
                        ResultMsg<FlowData> flowDataResultMsg = etechTaskController.getTaskDataReal(autoExecuteList.get(0).get("id_").toString(), "pc");
                        FlowData flowData = flowDataResultMsg.getData();
                        autoExecuteFlowParam.setData(flowData.getData());
                        autoExecuteFlowParam.setInstanceId(autoExecuteInstanceId);
                        autoExecuteFlowParam.setTaskId(autoExecuteList.get(0).get("id_").toString());
                        autoExecuteFlowParam.setAction(ActionType.AGREE.getKey());
                        autoExecuteFlowParam.setOpinion("系统自动通过");
                        log.info("autoExecuteFlowParam {}", autoExecuteFlowParam.getData());
                        IUser currentUser = ContextUtil.getCurrentUser();
                        ContextUtil.setCurrentUser(EtechUserUtil.getUserAdmin());
                        new DefualtTaskActionCmd(autoExecuteFlowParam).executeCmd();
                        ContextUtil.setCurrentUser(currentUser);
                    }
                }
            }

        }
    }

    private void autoSubmitNodeSimple(FlowRequestParam flowParam, DefualtTaskActionCmd taskModel) {
        String nodeAction = null;
        if (flowParam != null && flowParam.getAction() != null) {
            nodeAction = flowParam.getAction();
        } else {
            log.info("flowParam、getAction 至少一个为 null ");
            return;
        }

        String nodeKey = null;
        if (taskModel != null && taskModel.getBpmTask() != null && taskModel.getBpmTask().getNodeId() != null) {
            nodeKey = taskModel.getBpmTask().getNodeId();
        } else {
            log.info("taskModel、BpmTask、nodeKey 至少一个为 null ");
            return;
        }

        if (isNextNodeAuto(nodeAction, nodeKey)) {
            FlowRequestParam autoExecuteFlowParam = new FlowRequestParam();
            String autoExecuteInstanceId = flowParam.getInstanceId();
            if (StrUtil.isNullOrUndefined(autoExecuteInstanceId)) {
                log.info("autoExecuteInstanceId 为 null 或空 ");
            } else {
                JdbcTemplate jdbcTemplate = sysDataSourceService.getJdbcTemplateByKey(DBConstant.PLAN_DB);
                List<Map<String, Object>> autoExecuteList = jdbcTemplate.queryForList("SELECT id_ FROM bpm_task WHERE inst_id_=?", autoExecuteInstanceId);
                if (autoExecuteList.size() == 1) {
                    if (autoExecuteList.get(0).get("id_") == null) {
                        log.info("get bpm_task id_ == null");
                    } else {
                        autoExecuteFlowParam.setInstanceId(autoExecuteInstanceId);
                        autoExecuteFlowParam.setTaskId(autoExecuteList.get(0).get("id_").toString());
                        autoExecuteFlowParam.setAction(ActionType.AGREE.getKey());
                        autoExecuteFlowParam.setOpinion("系统自动通过");
                        IUser currentUser = ContextUtil.getCurrentUser();
                        ContextUtil.setCurrentUser(EtechUserUtil.getUserAdmin());
                        new DefualtTaskActionCmd(autoExecuteFlowParam).executeCmd();
                        ContextUtil.setCurrentUser(currentUser);
                    }
                }
            }

        }
    }

    private boolean isNextNodeAuto2(String nodeAction, String nodeKey) {
        return true;

    }

    private boolean isNextNodeAuto(String nodeAction, String nodeKey) {
        HashSet<String> targetActionSet = new HashSet<>();
        targetActionSet.add("agree");
        targetActionSet.add("oppose");
        if (targetActionSet.contains(nodeAction) && nodeKey.endsWith("_NEXTNODEAUTO")) {
            return true;
        }

        if (nodeAction.equals("agree") && nodeKey.endsWith("_IFAGREENEXTNODEAUTO")) {
            return true;
        }

        if (nodeAction.equals("oppose") && nodeKey.endsWith("_IFOPPOSENEXTNODEAUTO")) {
            return true;
        }

        return false;

    }

    public void handleTurnTask(JSONObject jsonObject) {
        Object buttonType = jsonObject.get("buttonType");
        if (buttonType == null) {
            return;
        }

        if (!"turn".equals(buttonType.toString().trim())) {
            return;
        }


        EtechTaskOpinionExt taskOpinionExt = JSONObject.toJavaObject(jsonObject.getJSONObject("taskOpinionExt"), EtechTaskOpinionExt.class);
        JSONArray addUserArr = jsonObject.getJSONArray("addUserList");
        if (addUserArr.size() == 0) {
            return;
        }


        List addUserIdList = new ArrayList();
        List addUserNameList = new ArrayList();
        for (Object item : addUserArr) {
            JSONObject addUser = JSON.parseObject(item.toString());
            addUserIdList.add(addUser.get("userId").toString());
            addUserNameList.add(addUser.get("userName").toString());
        }


        String currentId = ContextUtil.getCurrentUserId();
        String currentName = ContextUtil.getCurrentUserName();

        EtechTaskOpinionExt opinionExt = new EtechTaskOpinionExt();
        opinionExt.setId(IdUtil.getSuid());
        opinionExt.setInstId(taskOpinionExt.getInstId());
        opinionExt.setSupInstId("0");
        opinionExt.setTaskId("0");
        opinionExt.setTaskKey("turn");
        opinionExt.setTaskName(taskOpinionExt.getTaskName() + " > 转办");
        opinionExt.setAssignInfo(taskOpinionExt.getAssignInfo());
        opinionExt.setApprover(currentId);
        opinionExt.setApproverName(currentName);
        opinionExt.setApproveTime(new Date());
        // opinionExt.setOpinion("转给：" + String.join(" ", addUserNameList));
        opinionExt.setStatus("agree");
        opinionExt.setCreateBy(currentId);
        opinionExt.setCreateTime(DateUtil.offsetSecond(taskOpinionExt.getCreateTime(), -1));
        opinionExt.setDurMs(0L);
        taskOpinionExtMapper.insert(opinionExt);


        EtechEmailMessage emailMessage = new EtechEmailMessage();
        emailMessage.setSubject("转办通知");
        emailMessage.setTo(String.join(",", addUserIdList));
        // emailMessage.setBcc("1307");


        ResultMsg<FlowData> resultMsg = null;
        String subject = "";
        try {
            resultMsg = bpmTaskController.getTaskData(taskOpinionExt.getTaskId(), "");
            if (resultMsg != null && resultMsg.getIsOk()) {
                BpmFlowData flowData = (BpmFlowData) resultMsg.getData();

                if (flowData instanceof BpmFlowTaskData) {
                    IBpmTask task = ((BpmFlowTaskData) flowData).getTask();
                    subject = task.getSubject();
                }
            }
        } catch (Exception e) {
            log.debug("任务转办出错：" + e.getMessage());
            throw new BusinessMessage("任务转办出错： " + e.getMessage());

        }

        String content = "<div style=\"font-size:16px; font-family: 等线\">\n" +
                "    <div style=\"font-family: 等线\">[" + currentName + "] 向您转办了任务，请前往平台查看：</div>\n" +
                "    <br/>\n" +
                "    <div style=\"margin-left:30px;\">\n" +
                "    <table style=\"font-size:16px;\">\n" +
                "        <tr>\n" +
                "            <td style=\" font-family: 等线; color:#7f7f7f; font-weight:bold; text-align:right\">流程名称：</td>\n" +
                "            <td style=\" font-family: 等线;\">" + taskOpinionExt.getDefName() + "</td>\n" +
                "        </tr>\n" +
                "        <tr>\n" +
                "            <td style=\" font-family: 等线; color:#7f7f7f; font-weight:bold; text-align:right\">节点名称：</td>\n" +
                "            <td style=\" font-family: 等线;\">" + taskOpinionExt.getTaskName() + "</td>\n" +
                "        </tr>\n" +
                "        <tr>\n" +
                "            <td style=\" font-family: 等线; color:#7f7f7f; font-weight:bold; text-align:right\">任务名称：</td>\n" +
                "            <td style=\" font-family: 等线;\">" + subject + "</td>\n" +
                "        </tr>\n" +
                "    </table>\n" +
                "    </div>\n" +
                "    <br/>\n" +
                "    <a href='" + RequestHolder.getUrl() + "/index.html?link=/bpm/vueForm/taskComplete.html?taskId=" + taskOpinionExt.getTaskId() + "|" + taskOpinionExt.getTaskName() + "' style=\"text-decoration: none; color:#0070c0; font-weight:bold\">点击此处进入待办页面（请使用谷歌浏览器查看）</a>\n" +
                "    <br/>\n" +
                "    <br/>\n" +
                "    <div style=\"margin-top: 10px; color: red; font-size: 14px\">此邮件为平台自动发送，请勿回复！</div>\n" +
                "</div>\n";

        emailMessage.setHtmlContent(content);
        etechMailService.sendMail(emailMessage);

    }


    private void sendCcMail(DefualtTaskActionCmd taskModel) {
        String instanceId = taskModel.getInstanceId();
        if (StringUtil.isEmpty(instanceId)) {
            return;
        }
        //判断是否是通用流程中心的抄送
        List<Map<String, Object>> bpmCenterList = jdbcTemplate.queryForList(
                "SELECT id,bc_code,bc_topic FROM bpm_center WHERE bpminstanceid = ?",
                instanceId
        );
        if (bpmCenterList.size() != 1) {
            return;
        }
        List<String> ccUserList = taskModel.getExtendConf().getJSONArray("users")
                .stream().map(x -> ((JSONObject) x).getString("id"))
                .collect(Collectors.toList());
        EtechEmailMessage msg = new EtechEmailMessage();
        //设置邮件收件人
        msg.setTo(String.join(",", ccUserList));
        //设置邮件抄送人
        msg.setCc(ContextUtil.getCurrentUserId());
        //设置邮件的标题
        msg.setSubject("【通用流程中心】抄送任务通知");
        String content = "<div style=`font-size:16px;font-family:等线;mso-no-proof:yes`>"
                + "您好，" + ContextUtil.getCurrentUserName() + "向您抄送了一个任务，请前往平台查看：<br><br>"
                + "<div style=`margin-left:30px;`><table style=`font-size:16px;`>"
                + "<tr><td style=`font-family:等线;color:#7f7f7f; font-weight:bold; text-align:right`>" + "流水号："
                + "</td><td style=`font-family:等线`>" + String.valueOf(bpmCenterList.get(0).get("bc_code")) + "</td></tr>"
                + "<tr><td style=`font-family:等线;color:#7f7f7f; font-weight:bold; text-align:right`>" + "主题："
                + "</td><td style=`font-family:等线`>" + String.valueOf(bpmCenterList.get(0).get("bc_topic")) + "</td></tr>"
                + "<tr><td style=`font-family:等线;color:#7f7f7f; font-weight:bold; text-align:right`>" + "抄送人："
                + "</td><td style=`font-family:等线`>" + ContextUtil.getCurrentUserName() + "</td></tr>"
                + "<tr><td style=`font-family:等线;color:#7f7f7f; font-weight:bold; text-align:right`>" + "抄送备注："
                + "</td><td style=`font-family:等线`>" + taskModel.getOpinion() + "</td></tr>"
                + "<tr><td style=`font-family:等线;color:#7f7f7f; font-weight:bold; text-align:right`>" + "抄送节点："
                + "</td><td style=`font-family:等线`>" + taskModel.getBpmTask().getName() + "</td></tr>"
                + "</table></div><br>"
                + "<span style='background:yellow;mso-highlight:yellow'>"
                + "&nbsp&nbsp请您及时前往平台进行查看，谢谢！</span><br><br>"
                + "&nbsp&nbsp请至ETECH/通用流程中心/我的流程中心抄送,登录后查看。<br>"
                + "&nbsp&nbsp <a href='http://etech.stcetech.ad01.sec.com/index.html?link=http://etech.stcetech.ad01.sec.com/form/formCustSql/view/formCustSqlView.html?code=bpmCenterCc|我的流程中心抄送' style=`text-decoration: none; color:#0070c0; font-weight:bold`>点击进入我的流程中心抄送（注意使用谷歌浏览器查看）</a><br><br> "
                +"<br><br><div style=\"margin-top: 10px; color: red; font-size: 14px\">此邮件为平台自动发送，请勿回复！</div></div>";
        msg.setHtmlContent(content);
        etechMailService.sendMail(msg);
    }


}
